﻿using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;

public class EventManager
{
    static Dictionary<int, Delegate> listenerDic = new Dictionary<int, Delegate>();

    public static void ClearListener()
    {
        listenerDic.Clear();
    }

    public static void TriggerEvent(int eventID)
    {
        Delegate d;
        if (!listenerDic.TryGetValue(eventID, out d))
            return;

        if (d == null)
            return;

        Delegate[] callbacks = d.GetInvocationList();
        for (int i = 0; i < callbacks.Length; i++)
        {
            Action callback = callbacks[i] as Action;

            if (callback == null)
            {
                Debug.LogError("Event Listener is Null");
                return;
            }
            callback();
        }
    }

    public static void TriggerEvent<T>(int eventID, T arg1)
    {
        Delegate d;
        if (!listenerDic.TryGetValue(eventID, out d))
            return;

        if (d == null)
            return;

        var callbacks = d.GetInvocationList();
        for (int i = 0; i < callbacks.Length; i++)
        {
            Action<T> callback = callbacks[i] as Action<T>;

            if (callback == null)
            {
                Debug.LogError("Event Listener is Null  EventID:" + eventID);
                return;
            }
            callback(arg1);
        }
    }

    public static void TriggerEvent<T, U>(int eventID, T arg1, U arg2)
    {
        Delegate d;
        if (!listenerDic.TryGetValue(eventID, out d))
            return;

        if (d == null)
            return;

        var callbacks = d.GetInvocationList();
        for (int i = 0; i < callbacks.Length; i++)
        {
            Action<T, U> callback = callbacks[i] as Action<T, U>;

            if (callback == null)
            {
                Debug.LogError("Event Listener is Null  EventID:" + eventID);
                return;
            }
            callback(arg1, arg2);
        }
    }

    public static void TriggerEvent<T, U, V>(int eventID, T arg1, U arg2, V arg3)
    {
        Delegate d;
        if (!listenerDic.TryGetValue(eventID, out d))
            return;

        if (d == null)
            return;

        var callbacks = d.GetInvocationList();
        for (int i = 0; i < callbacks.Length; i++)
        {
            Action<T, U, V> callback = callbacks[i] as Action<T, U, V>;

            if (callback == null)
            {
                Debug.LogError("Event Listener is Null");
                return;
            }
            callback(arg1, arg2, arg3);
        }
    }

    public static void TriggerEvent<T, U, V, W>(int eventID, T arg1, U arg2, V arg3, W arg4)
    {
        Delegate d;
        if (!listenerDic.TryGetValue(eventID, out d))
            return;

        if (d == null)
            return;

        var callbacks = d.GetInvocationList();
        for (int i = 0; i < callbacks.Length; i++)
        {
            Action<T, U, V, W> callback = callbacks[i] as Action<T, U, V, W>;

            if (callback == null)
            {
                Debug.LogError("Event Listener is Null");
                return;
            }

            callback(arg1, arg2, arg3, arg4);
        }
    }

    public static void AddEventListener(int eventID, Action handler)
    {
        OnListenerAdding(eventID, handler);
        listenerDic[eventID] = (Action)listenerDic[eventID] + handler;
    }
    public static void AddEventListener<T>(int eventID, Action<T> handler)
    {
        OnListenerAdding(eventID, handler);
        listenerDic[eventID] = (Action<T>)listenerDic[eventID] + handler;
    }
    public static void AddEventListener<T, U>(int eventID, Action<T, U> handler)
    {
        OnListenerAdding(eventID, handler);
        listenerDic[eventID] = (Action<T, U>)listenerDic[eventID] + handler;
    }
    public static void AddEventListener<T, U, V>(int eventID, Action<T, U, V> handler)
    {
        OnListenerAdding(eventID, handler);
        listenerDic[eventID] = (Action<T, U, V>)listenerDic[eventID] + handler;
    }

    public static void AddEventListener<T, U, V, W>(int eventID, Action<T, U, V, W> handler)
    {
        OnListenerAdding(eventID, handler);
        listenerDic[eventID] = (Action<T, U, V, W>)listenerDic[eventID] + handler;
    }

    private static void OnListenerAdding(int eventID, Delegate listener)
    {
        if (!listenerDic.ContainsKey(eventID))
        {
            listenerDic.Add(eventID, null);
        }

        Delegate d = listenerDic[eventID];
        if (d != null && d.GetType() != listener.GetType())
        {
            throw new Exception(string.Format(
                   "Try to add not correct event {0}. Current type is {1}, adding type is {2}.",
                   eventID, d.GetType().Name, listener.GetType().Name));
        }
    }


    public static void RemoveEventListener(int eventID, Action handler)
    {
        if (handler == null)
        {
            Debug.Log("传入Handler为空 " + eventID);
            return;
        }
        if (OnListenerRemoving(eventID, handler))
        {
            listenerDic[eventID] = (Action)listenerDic[eventID] - handler;
            OnListenerRemoved(eventID);
        }
    }

    public static void RemoveEventListener<T>(int eventID, Action<T> handler)
    {
        if (OnListenerRemoving(eventID, handler))
        {
            listenerDic[eventID] = (Action<T>)listenerDic[eventID] - handler;
            OnListenerRemoved(eventID);
        }
    }
    public static void RemoveEventListener<T, U>(int eventID, Action<T, U> handler)
    {
        if (OnListenerRemoving(eventID, handler))
        {
            listenerDic[eventID] = (Action<T, U>)listenerDic[eventID] - handler;
            OnListenerRemoved(eventID);
        }
    }
    public static void RemoveEventListener<T, U, V>(int eventID, Action<T, U, V> handler)
    {
        if (OnListenerRemoving(eventID, handler))
        {
            listenerDic[eventID] = (Action<T, U, V>)listenerDic[eventID] - handler;
            OnListenerRemoved(eventID);
        }
    }
    public static void RemoveEventListener<T, U, V, W>(int eventID, Action<T, U, V, W> handler)
    {
        if (OnListenerRemoving(eventID, handler))
        {
            listenerDic[eventID] = (Action<T, U, V, W>)listenerDic[eventID] - handler;
            OnListenerRemoved(eventID);
        }
    }

    private static bool OnListenerRemoving(int eventID, Delegate listener)
    {
        if (!listenerDic.ContainsKey(eventID))
        {
            return false;
        }

        Delegate d = listenerDic[eventID];
        if ((d != null) && (d.GetType() != listener.GetType()))
        {
            throw new Exception(string.Format(
                "Remove listener {0}\" failed, Current type is {1}, adding type is {2}.",
                eventID, d.GetType(), listener.GetType()));
        }
        else
        {
            return true;
        }
    }
    private static void OnListenerRemoved(int eventID)
    {
        if (listenerDic.ContainsKey(eventID) && listenerDic[eventID] == null)
        {
            listenerDic.Remove(eventID);
        }
    }
}

